package com.a918.consensus;

public abstract class Node {
  private final EarthPosition position;
  private Proposal output;
  private double terminationTime;
  private double credit;
  private double token;

  Node(EarthPosition position) {
    this.position = position;
  }

  Node(EarthPosition position, double credit, double token) {
    this.position = position;
    this.credit = credit;
    this.token = token;
  }

  abstract void onStart(Simulation simulation);

  abstract void onTimerEvent(TimerEvent timerEvent, Simulation simulation);

  abstract void onMessageEvent(MessageEvent messageEvent, Simulation simulation);

  boolean hasTerminated() {
    return output != null;
  }

  void terminate(Proposal output, double terminationTime) {
    this.output = output;
    this.terminationTime = terminationTime;
  }

  abstract boolean addBlock(Block block);



  /** The great-circle distance to another node, in meters. */
  double getDistance(Node that) {
    return this.position.getDistance(that.position);
  }

  double getTerminationTime() {
    return terminationTime;
  }
  public double getCredit(){
    return credit;
  }

  void setCredit(double credit){
    this.credit = credit;
  }

  public double getToken(){
    return token;
  }
  void setToken(double token){
    this.token = token;
  }

  EarthPosition getPosition(){
    return position;
  }
  void restart(){
    output = null;
    terminationTime=0;
  }
  public Proposal getOutput(){
    return output;
  }
}

/** A node which has simply failed, and thus ignores all events. */
class FailedNode extends Node {
  FailedNode(EarthPosition position) {
    super(position);
  }
  FailedNode(EarthPosition position, double credit, double token) {
    super(position,credit,token);
  }

  @Override public void onStart(Simulation simulation) {
    // No-op.
  }

  @Override public void onTimerEvent(TimerEvent timerEvent, Simulation simulation) {
    // No-op.
  }

  @Override public void onMessageEvent(MessageEvent messageEvent, Simulation simulation) {
    // No-op.
  }

  @Override public boolean addBlock(Block block) {
    // No-op.
    return false;
  }
}

